/**
 * @author mengqinghui
 * @date 2013/05/28
 * autocomplete 扩展
 * @updated 2014/03/27:
 *
 * （1）增加_displayKey属性，如果displayKey有值，则所有suggest选项渲染时
 * 采用displayKey字段存储的值来进行显示
 *  (2) 重构labelKey,valueKey,去掉nameKey，统一采用displayKey
 */
$.widget("ui.autocomplete", $.ui.autocomplete, {
	version: '0.0.1',
    _displayKey: '$$autocompleteDisplayKey',
    _showKey:"$$autocompleteShowKey",
    options: {
        labelKey: 'label',
        valueKey: 'id'
    },
    getSelectedItem: function() {
        return this.selectedItem;
    },
    getItems: function() {
        var items = [];
        if (this.options.multiple) {
            this.element.parent().find('span.ui-suggest-value').each(function() {
                items.push($(this).data('data'));
            });
        } else {
            if (this.selectedItem) {
                items = [this.selectedItem];
            }
        }

        return items;
    },
    setSelectedItem: function(item) {
        this._value(item);
        this.selectedItem = item;
    },
    /**
     * 设置输入验证合法性
     *
     *
     * @param status  boolean
     */
    setValidStatus: function(status) {
        this.noResultPanel.data('valid', status);
    },
    _renderMenu: function(ul, items) {
        var that = this;
        var header = this.options.header;
        if (header) {
            ul.append(
            	$('<li class="ui-menu-header">' + header + '</li>').data('ui-autocomplete-item', {})
            );
        }
        $.each(items, function(index, item) {
            that._renderItemData(ul, item);
        });
        var footer = this.options.footer;
        if (this.options.needFooter && footer) {
            ul.append(
            	$('<li class="ui-menu-footer">' + footer + '</li>').data('ui-autocomplete-item', {})
            );
        }
    },

    /**
     * 覆写原来的template
     *
     *
     * @param ul
     * @param item
     * @returns
     */
    _renderItem: function(ul, item) {
        var self = this,
            template = self.options.template || function(item) {
                return item[self._displayKey];
            };
        return $("<li>")
            .append('<a>' + template.call(this, item) + '</a>')
            .appendTo(ul);
    },
    __response: function(content) {
        if (content) {
            content = this._normalize(content);
        }
        this._trigger("response", null, {
            content: content
        });
        if (!this.options.disabled && content && content.length && !this.cancelSearch) {
            this._suggest(content);
            this._trigger("open");
        } else {
            // use ._close() instead of .close() so we don't cancel future searches

            if (this.options.people) {
                var $menuElement = this.menu.element;
                $menuElement.show();
                $menuElement.find('.ui-menu-item').remove();
                var noResult = this.options.noResult || '没有结果';

                var $noResult = $('<li class="ui-menu-info ui-menu-noresult">' + noResult + '</li>');
                if (self.noResultPanel) {
                    self.noResultPanel.position({
                        of: this.element,
                        my: "left top",
                        at: "left bottom",
                        collision: "none"
                    });
                }

                if (!$menuElement.find('.ui-menu-noresult').length) {
                    if ($menuElement.find('.ui-menu-header').length) {
                        $menuElement.find('.ui-menu-header').after($noResult);
                    } else {
                        $menuElement.prepend($noResult);
                    }
                    this.menu.blur();
                } else {
                    $menuElement.find('.ui-menu-noresult').show();
                }

            } else {
                this._close();
            }
        }
    },

    getValue: function() {
        return $(this.element).attr('data-id') || '';
    },

    setValue: function(item) {
        var self = this;
        self.prevItem = item;
        if (self.options.multiple) {
            self.addValue(item);
            return false;
        } else {

            if (!item) {
                self.element.removeAttr('data-id').val('');
            } else {
                self.element.attr('data-id', item[this.options.valueKey]);
                self._value(item.label);
            }

            self.element.removeClass('valid-error');
            self.setValidStatus(true);
        }

    },

    addValue: function(item, isInit) {
        var self = this;
        var options = self.options;
        var items = self.getResultData && self.getResultData();
        items = items || [];
        var isValidItem = false;
        var itemName, keyName;
        if (!item) {
            return;
        }

        item.name = $.trim(item[self._displayKey]);
        item.value = $.trim(item[options.valueKey]);
        item.label = $.trim(item[options.labelKey]);

        if (options.multipleProcess) {
            item = options.multipleProcess(item);
        }

        if (!isInit && options.multipleValid) {
            isValidItem = $.grep(items, function(key) {
                itemName = item.name || item.value || '';
                keyName = key.name || key.value || '';
                return (itemName.toLowerCase() === keyName.toLowerCase());
            }).length > 0;
            // 如果不合法则不添加
            if (!isValidItem) {
                return;
            }
        }

        var dataArr = [];
        var valueKey = options.valueKey || 'id';
        items = self.getItems();

        var id = item[valueKey];
        var label = item.label;
        var displayedLabel = item[self._displayKey];
        var showLabel  =item[self._showKey] || label ;
        var $span, tpl;
        if (items) {
            $.each(items, function(i, oItem) {
                if (oItem[valueKey]) {
                    dataArr.push(oItem[valueKey]);
                }
            });
        }
        self._value('');
        if (this.options.mustInAutoComplete && !id) {
            return '';
        }
        if (id && $.inArray(id, dataArr) < 0) {
            dataArr.push(id);
        }

        $(this.element).attr('data-id', dataArr.join(','));

        if (id) {
            if ($.inArray(id, dataArr) !== -1) {
                $span = $(this.element).parent().find('span[data-tag-id="' + id + '"]');
            }
        } else if (label) {
            $span = $(this.element).parent().find('span[data-tag-label="' + label + '"]');
        }

        if ($span && $span.length > 0) {
            $span.effect('highlight', {}, 3000);
        } else {
            tpl = $('<span data-tag-id="' + (id || '') + '"class="ui-suggest-value tagmanagerTag" data-tag-label="' + label + '">' + showLabel +
                '<a class="tagmanagerRemoveTag" title="Remove" href="#">x</a></span>').data('data', item);
            $(this.element).after(tpl);
        }
    },

    removeValue: function(el) {
        var $item = $(el).parents('.tagmanagerTag');
        var item = $item.data('data');
        if(item == null){
            return ;
        }
        $item.remove();
        var dataId = $(this.element).attr('data-id');
        var dataIds = [];
        if (dataId) {
            dataIds = dataId.split(',');
        }
        var value = item[this.options.valueKey];
        var index = $.inArray(value, dataIds);
        dataIds.splice(index, 1);
        if (dataIds.length <= 0) {
            $(this.element).removeAttr('data-id');
        } else {
            $(this.element).attr('data-id', dataIds.join(','));
        }
    },

    getValidStatus: function() {
        return !this.element.hasClass('valid-error');
    },

    showPanel: function() {
        this.panel.show();
        this.noResultPanel.hide();
    },

    hidePanel: function() {
        this.panel.hide();
    },

    setValidStausCss: function(status) {
        var self = this;
        var _options = self.options;
        if (status && status == 'error') {
            if (_options.validate && _options.validate === true) {
                self.element.addClass('valid-error');
            }
        } else {
            self.element.removeClass('valid-error');
        }
    },

    /**
     *
     * 每次请求返回的验证函数
     * 验证结果分为3中{
     *     noresult: '' , 完全没有数据
     *     oneresult: '', 只匹配到一条数据
     *     moreresult: '' 匹配到多个数据
     * }
     * 三种结果都会调用相应的处理函数，处理函数在业务逻辑处理
     *
     * @param content 返回的数据
     */
    validate: function(content) {
        var self = this;
        var options = self.options;
        self.element.removeAttr('data-id');
        if (!content || !content.length) {
            var onNoResult = options.onNoResult || function() {
                    if (self.options.noResult && options.validate) {
                        self.noResultPanel.html(self.options.noResult).show();
                        self.noResultPanel.position({
                            of: this.element,
                            my: "left top",
                            at: "left bottom",
                            collision: "none"
                        });
                        self.setValidStatus(false);
                        self.setValidStausCss('error');
                    }
                };
            onNoResult.call(self);

        } else if (content && content.length == 1) {
            var onOneResult = options.onOneResult || function(item) {};
            self.noResultPanel.hide();
            onOneResult.call(this, content[0]);
        } else {
            var onMoreResult = options.onMoreResult || function() {
                    self.setValidStatus(false);
                };
            self.noResultPanel.hide();
            onMoreResult();
        }
    },

    _initPanel: function() {
        var self = this;
        var options = self.options;
        var appendTo = self._appendTo();
        var element = self.element;
        var panel = $('<div class="ui-suggest-panel"></div>');

        panel.attr('id', 'ui-suggest-' + this.element.attr('id'))
            .appendTo(appendTo);

        self.panel = panel;

        var renderPanel = options.renderPanel;
        self._on(panel, {
            'mousedown': function(event) {
                event.preventDefault();

                if (!$(event.target).closest(".ui-suggest-panel").length) {
                    // 
                } else {
                    var item = $(event.target).data('initpanel-item');
                    if (!item) {
                        return false;
                    }
                    if (false !== self._trigger("select", event, {
                        item: item
                    })) {
                        self._value(item.value);
                    }
                    self.selectedItem = item;
                    self.hidePanel();
                }
                return false;
            }
        });
        $(self.element).on('focus.showPanel', function() {
            var panel = self.panel;
            self._delay(function() {

                self.document.one("mousedown", function(event) {
                    if (event.target !== element[0] &&
                        event.target !== panel[0] && !$.contains(panel[0], event.target)) {
                        self.hidePanel();
                        self.noResultPanel.hide();
                    }
                });
            });
            renderPanel.call(self, function(data) {
                var panel = self.panel;
                panel.empty();
                self.showPanel();
                panel.position({
                    of: element,
                    my: "left top",
                    at: "left bottom",
                    collision: "none"
                });
                $.each(data, function(i, item) {
                    $('<a href="javascript:;" class="ui-suggest-item">' + item.label +
                        '</a>').appendTo(panel).data('initpanel-item', item);
                });
            });
        }).on('keyup', function() {
            if ($(this).val().length === 0) {
                self.showPanel();
            } else {
                self.hidePanel();
            }
        });
    },

    _initNoResult: function() {
        var self = this;
        var appendTo = self._appendTo();
        var element = self.element;
        var width = $(element).css('width');
        self.noResultPanel = $('<div class="ui-suggest-panel noresult"></div>')
            .attr('id', 'ui-suggest-' + this.element.attr('id')).data('valid', true)
            .css({
                width: width
            }).appendTo(appendTo);

        $(document).on('mousedown.hideNoResult', function() {
            self.noResultPanel.hide();
        });
    },

    multiplesearch: function() {
        var term = this.term;
        var options = this.options;
        var multiple = options.multiple;

        if (options.multiple) {
            if (term.slice(-1) === multiple) {
                var item = null;
                if (this.options.validate && this.getValidStatus()) {
                    item = this.prevItem;
                } else {
                    term = term.slice(0, -1);
                    if ($.trim(term)) {
                        item = {
                            name: term,
                            label: term
                        };
                    }
                }
                this.addValue(item);
                return false;
            }
        } else {

        }
    },

    init: function() {

        var self = this;
        var renderPanel = self.options.renderPanel;
        self._initNoResult();
        if (self.options.init) {
            self.options.init.call(self);
        }
        if (renderPanel) {
            self._initPanel();
        }

        if (this.options.multiple) {
            $(self.element).parent().on('click', 'a.tagmanagerRemoveTag', function(e) {
                var target = e.target;
                self.removeValue(target);
                return false;
            });
            var items = this.options.parseValue.call(this);
            $.each(items, function(i, item) {
                self.addValue(item, true);
            });
        }

        self.element.on('keyup', function(e) {
            if ($(this).val().length === 0) {
                self.setValidStatus(true);
                self._trigger("emptyvalue");
                self.setValue(null);
                self.setValidStausCss('valid');
            } else {
                var keyCode = $.ui.keyCode;
                if (self.options.multiple && e.keyCode == keyCode.ENTER && self.options.quickAdd) {
                    var term = self.element.val();
                    var item = null;
                    if ($.trim(term)) {
                        item = {
                            name: term,
                            label: term
                        };
                        self.addValue(item);
                    }
                }

            }
        }).on('blur', function() {
            if ($.trim(self.element.val()) !== '' && !self.element.attr('data-id')) {
                self.setValidStausCss('error');
            }
            if (self.options.validate && self.options.clearInvalid) {

                if (!self.getValidStatus()) {
                    self.element.val('');
                    self.setValidStausCss('valid');

                    if (self.options.onBlurEmpty) {
                        self.options.onBlurEmpty.call(self);
                    }
                }
            }
        });
    }
});